/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.uml_generator.model.impl;

import java.util.HashMap;
import java.util.Map;

import org.springframework.util.ObjectUtils;

import com.genia.toolbox.uml_generator.model.AbstractObject;
import com.genia.toolbox.uml_generator.model.StereotypeModel;

/**
 * implementation of {@link AbstractObject}.
 */
public abstract class AbstractObjectImpl
    implements AbstractObject
{
  /**
   * the name of the object.
   */
  private String name;

  /**
   * umlId of the object.
   */
  private String umlId;

  /**
   * the comment associated to the object.
   */
  private String comment;

  /**
   * the documentations that mark this object.
   */
  private final Map<String, StereotypeModel> stereotypes = new HashMap<String, StereotypeModel>();

  /**
   * the length of the object.
   */
  private transient Integer length = null;



  /**
   * add the {@link StereotypeModel} to the model.
   * 
   * @param stereotype
   *          the {@link StereotypeModel} to add
   * @see com.genia.toolbox.uml_generator.model.AbstractObject#addStereotype(StereotypeModel)
   */
  public void addStereotype(final StereotypeModel stereotype)
  {
    this.stereotypes.put(stereotype.getName(), stereotype);

  }



  /**
   * Indicates whether some other object is "equal to" this one.
   * 
   * @param obj
   *          the reference object with which to compare.
   * @return <code>true</code> if this object is the same as the obj argument;
   *         <code>false</code> otherwise.
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj)
  {
    if (obj == this) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (obj instanceof AbstractObject) {
      return getUmlId().equals(((AbstractObject) obj).getUmlId());
    }
    return false;
  }



  /**
   * getter for the comment property.
   * 
   * @return the comment
   */
  public String getComment()
  {
    return comment;
  }



  /**
   * returns the list of {@link StereotypeModel} that mark this object.
   * 
   * @return the list of {@link StereotypeModel} that mark this object
   * @see com.genia.toolbox.uml_generator.model.AbstractObject#getStereotypes()
   */
  public Map<String, StereotypeModel> getStereotypes()
  {
    return stereotypes;
  }



  /**
   * getter for the length property.
   * 
   * @return the length
   * @see com.genia.toolbox.uml_generator.model.AbstractJavaObject#getLength()
   */
  public Integer getLength()
  {
    return length;
  }



  /**
   * getter for the name property.
   * 
   * @return the name
   * @see com.genia.toolbox.uml_generator.model.AbstractJavaObject#getName()
   */
  public String getName()
  {
    return name;
  }



  /**
   * returns the UmlId of the object.
   * 
   * @return the UmlId of the object
   * @see com.genia.toolbox.uml_generator.model.AbstractJavaObject#getUmlId()
   */
  public String getUmlId()
  {
    return umlId;
  }



  /**
   * Returns a hash code value for the object. This method is supported for the
   * benefit of hashtables such as those provided by
   * <code>java.util.Hashtable</code>.
   * 
   * @return a hash code value for this object
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode()
  {
    return ObjectUtils.nullSafeHashCode(getUmlId());
  }



  /**
   * returns whether this element is tagged with a particular value.
   * 
   * @param stereotype
   *          the value to check.
   * @return <code>true</code> if an only if the element is tagged with the
   *         value.
   * @see com.genia.toolbox.uml_generator.model.AbstractObject#hasStereotype(java.lang.String)
   */
  public boolean hasStereotype(String stereotype)
  {
    return (getStereotype(stereotype) != null);
  }



  /**
   * returns the value of the given tag for the given element. Will return
   * <code>null</code> if the element is not tagged with the given tag.
   * 
   * @param stereotype
   *          the value to check.
   * @return the value of the given tag for the given element
   * @see com.genia.toolbox.uml_generator.model.AbstractObject#getStereotype(java.lang.String)
   */
  public StereotypeModel getStereotype(String stereotype)
  {
    return getStereotypes().get(stereotype);
  }



  /**
   * setter for the comment property.
   * 
   * @param comment
   *          the comment to set
   */
  public void setComment(String comment)
  {
    if (comment != null) {
      comment = comment.trim();
      if (!"".equals(comment)) {
        if (!comment.endsWith(".")) {
          comment += ".";
        }
        this.comment = comment;
      }
    }
    else {
      comment = null;
    }
  }



  /**
   * setter for the name property.
   * 
   * @param name
   *          the name to set
   * @see com.genia.toolbox.uml_generator.model.AbstractJavaObject#setName(java.lang.String)
   */
  public void setName(String name)
  {
    if (name != null) {
      name = name.trim();
    }
    if (name.matches("^[^(]*\\([0-9]+\\)$")) {
      int indexLParenthesis = name.indexOf('(');
      int indexRParenthesis = name.indexOf(')');
      setLength(new Integer(name.substring(indexLParenthesis + 1, indexRParenthesis)));
      name = name.substring(0, indexLParenthesis);
    }
    this.name = name;
  }



  /**
   * setter for the id property.
   * 
   * @param umlId
   *          the id to set
   * @see com.genia.toolbox.uml_generator.model.AbstractObject#setUmlId(String)
   */
  public void setUmlId(String umlId)
  {
    this.umlId = umlId;
  }



  /**
   * returns the original object if the current object is decorated.
   * 
   * @return the original object if the current object is decorated
   */
  public AbstractObject getUndecoraredObject()
  {
    return this;
  }



  /**
   * setter for the length property.
   * 
   * @param length
   *          the length to set
   */
  protected void setLength(Integer length)
  {
    this.length = length;
  }
}
